﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Globalization;
using XemlUtilities.DataSet;

namespace XemlUtilities.ISA
{
    public class Metabolites: DataTable
    {
        private XemlDataSet xds;
        private Guid xemlId;
        private string connectionString;

        #region constructors
        public Metabolites(Guid xemlId, string connectionString)
            :base()
        {
            using (gmdProfileService.XemlProfile.IsaExportDataTable dt = new gmdProfileService.XemlProfile.IsaExportDataTable(xemlId))
            {
                dt.GetXemlExperimentHeatMapData(connectionString);

                //"database_identifier"	"chemical_formula"	"smiles"	"inchi"	"metabolite_identification"	"mass_to_charge"	"fragmentation"	"modifications"	"charge"	"retention_time"
                //"taxid"	"species"	"database"	"database_version"	"reliability"	"uri"	"search_engine"	"search_engine_score"	"smallmolecule_abundance_sub"	"smallmolecule_abundance_stdev_sub"	"smallmolecule_abundance_std_error_sub" ...
                DataColumn dcDBId = new DataColumn("database_identifier", typeof(string));
                dcDBId.AllowDBNull = false;
                this.Columns.Add(dcDBId);
                DataColumn dcChemicalFormula = new DataColumn("chemical_formula", typeof(String));
                this.Columns.Add(dcChemicalFormula);
                DataColumn dcSmiles = new DataColumn("smiles", typeof(String));
                this.Columns.Add(dcSmiles);
                DataColumn dcInChi = new DataColumn("inchi", typeof(String));
                this.Columns.Add(dcInChi);
                DataColumn dcMetaboliteIdentification = new DataColumn("metabolite_identification", typeof(String));
                this.Columns.Add(dcMetaboliteIdentification);
                DataColumn dcMassToCharge = new DataColumn("mass_to_charge", typeof(String));
                this.Columns.Add(dcMassToCharge);
                DataColumn dcFragmentation = new DataColumn("fragmentation", typeof(String));
                this.Columns.Add(dcFragmentation);
                DataColumn dcModifications = new DataColumn("modifications", typeof(String));
                this.Columns.Add(dcModifications);
                DataColumn dcCharge = new DataColumn("charge", typeof(String));
                this.Columns.Add(dcCharge);
                DataColumn dcRetentionTime = new DataColumn("retention_time", typeof(String));
                this.Columns.Add(dcRetentionTime);
                DataColumn dcTaxId = new DataColumn("taxid", typeof(String));
                this.Columns.Add(dcTaxId);
                DataColumn dcSpecies = new DataColumn("species", typeof(String));
                this.Columns.Add(dcSpecies);
                DataColumn dcDatabase = new DataColumn("database", typeof(String));
                this.Columns.Add(dcDatabase);
                DataColumn dcDatabaseVersion= new DataColumn("database_version", typeof(String));
                this.Columns.Add(dcDatabaseVersion);
                DataColumn dcReliability = new DataColumn("reliability", typeof(String));
                this.Columns.Add(dcReliability);
                DataColumn dcUri = new DataColumn("uri", typeof(String));
                this.Columns.Add(dcUri);
                DataColumn dcSearchEngine = new DataColumn("search_engine", typeof(String));
                this.Columns.Add(dcSearchEngine);
                DataColumn dcSearchEngineScore = new DataColumn("search_engine_score", typeof(String));
                this.Columns.Add(dcSearchEngineScore);
                DataColumn dcSmallmoleculeAbundanceSub = new DataColumn("smallmolecule_abundance_sub", typeof(String));
                this.Columns.Add(dcSmallmoleculeAbundanceSub);
                DataColumn dcSmallmoleculeAbundanceStdevSub = new DataColumn("smallmolecule_abundance_stdev_sub", typeof(String));
                this.Columns.Add(dcSmallmoleculeAbundanceStdevSub);
                // add the actual data
                foreach (DataColumn dc in dt.Columns.Cast<DataColumn>().Skip(5))
                {
                    this.Columns.Add(dc.ColumnName, dc.DataType);
                }

                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
                int i = 0;
                foreach (DataRow r in dt.Rows) {
                    DataRow newRow = this.NewRow();
                    newRow[dcDBId] = r.Field<String>("identifier");
                    newRow[dcChemicalFormula] = r.Field<String>("chemical_formula");
                    newRow[dcSmiles] = String.Empty;
                    newRow[dcInChi] = r.Field<String>("comment[inchi]");
                    newRow[dcMetaboliteIdentification] = String.Empty;
                    newRow[dcMassToCharge] = String.Empty;
                    newRow[dcFragmentation] = String.Empty;
                    newRow[dcModifications] = String.Empty;
                    newRow[dcCharge] = String.Empty;
                    newRow[dcRetentionTime] = String.Empty;
                    newRow[dcTaxId] = String.Empty;
                    newRow[dcSpecies] = String.Empty;
                    newRow[dcDatabase] = String.Empty;
                    newRow[dcDatabaseVersion] = String.Empty;
                    newRow[dcReliability] = String.Empty;
                    newRow[dcUri] = String.Empty;
                    newRow[dcSearchEngine] = String.Empty;
                    newRow[dcSmallmoleculeAbundanceSub] = String.Empty;
                    newRow[dcSmallmoleculeAbundanceStdevSub] = String.Empty;

                    foreach (DataColumn dc in dt.Columns.Cast<DataColumn>().Skip(5))
                	{
                        newRow[dc.ColumnName] = dt.Rows[i][dc.ColumnName];
					}

                    this.Rows.Add(newRow);
                    i++;
                }
            }
        }
        #endregion constructors
        public IEnumerable<DataColumn> GetColumns()
        {
            return this.Columns.Cast<DataColumn>();
        }

        public void Write(System.IO.Stream s)
        {
            System.IO.StreamWriter txtWriter = new System.IO.StreamWriter(s);
            txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(this.GetColumns().Select(x => x.Caption).Select(c => c.ToString()).ToList())));
            foreach (DataRow r in this.Rows)
            {
                txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(r.ItemArray.Select(c => c.ToString()).ToList())));
            }
            txtWriter.Flush();
        }

        public static MemoryStream GetStream(Guid xemlId, string connectionstring)
        {
            using (Metabolites dt = new Metabolites(xemlId, connectionstring))
            {
                MemoryStream res = new MemoryStream();
                dt.Write(res);
                res.Seek(0, SeekOrigin.Begin);
                return res;
            }
        }

        public static string GetFileName(XemlDataSet xds)
        {
            return string.Format("m_{0}.tsv", xds.Document.Single().PutativeFileName);
        }
    }
}
